 #include<iostream>
#include<algorithm>
#include<utility>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<sstream>
#include<cmath>
#include<ctime>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
 
#include<numeric>
#include<limits>
using namespace std;
typedef long long ll;
#define inf 0x3fffffff
const double pi=acos(-1.0);
#define eps (1e-15)
#define clr clear
#define PB push_back
#define SZ(x) ((int)(x).size())
#define MP make_pair
#define X first
#define Y second
#define PII pair<int,int>
#define VI vector<int>
#define VD vector<double>
#define VS vector<string>dd
#define FORD(i,b,c) for(int (i)=(b);(i)>=c;(i)--)
#define REPD(i,c) FORD(i,c,0)
#define FOR(i,b,c) for(int i=(b);i<(c);i++)
#define REP(i,c) FOR(i,0,c)
#define PQ priority_queue
#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)
#ifdef DBG
#define see(x) (cerr<<"[Line : "<< __LINE__<<"] : "<<#x<<"="<<x<<endl)
#define se(x) cerr<<x<<" "
#else
#define see(x) //
#define se(x) //
#endif

#define maxn  1030
int n,m;
vector<int> block[maxn];
int g[maxn][maxn];
int first[maxn],next[maxn*1000],E[maxn*maxn];
int M;
void init()
{
	M=0;
	memset(first,-1,sizeof(first));
}
void insert(int a,int b)
{
	next[M]=first[a];
	first[a]=M;
	E[M]=b;
	M++;
}

/**********无向图求块，把快都存在了block里面**************************/
int bcnt ,dindex,low[maxn],dfn[maxn],top,sta[maxn];//bcnt是块数，从1到bcnt
void dfs(int u,int father)
{
	int v,e,cnt=0;
	dfn[u]=low[u]=++dindex;
	sta[top++]=u;
	for(e=first[u]; e!=-1; e=next[e])
	{
		v=E[e];
		if(!dfn[v])
		{
			cnt++;
			dfs(v,u);
			low[u]=min(low[u],low[v]);
			if((father!=-1 && low[v]>=dfn[u])|| (father==-1 && cnt>1))
			{
				bcnt++;
				block[bcnt].clear();
				for(block[bcnt].push_back(u),sta[top]=-1;sta[top]!=v; block[bcnt].push_back(sta[--top]));
					
			}
		}
		else if(v!=father)
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
}
void getblock()
{
	int i,j,ans;
	bcnt=dindex=0;
	memset(low,0,sizeof(low));
	memset(dfn,0,sizeof(dfn));
	for(i=1; i<=n; i++)
	{
		if(dfn[i]==0)
		{
			top=0;
			dfs(i,-1);
		}
		if(top>0)
		{
			bcnt++;
			block[bcnt].clear();
			while(top>0)
			{
				block[bcnt].push_back(sta[--top]);
			}
		}
	}
}
/**********无向图求块，把快都存在了block里面**************************/
int flag[maxn],two[maxn],use[maxn];
int cir(int i,int k)
{
	int e,v;
	two[i]=k;
	for(e=first[i]; e!=-1; e=next[e])
	{
		v=E[e];
		if(use[v])
		{
			if(!two[v])
			{
				return cir(v,-k);
			}
			if(two[v]==k)
			return 1;
		}
	}
	return 0;
}
void solve()
{
	int i,j;
	memset(flag,0,sizeof(flag));
	for(i=1; i<=bcnt; i++)
	{
		memset(two,0,sizeof(two));
		memset(use,0,sizeof(use));
		for(j=0; j<block[i].size(); j++)
		{
			use[block[i][j]]=1;
		}
		if(cir(block[i][0],1))
		{
			for(j=0; j<block[i].size(); j++)
			{
				flag[block[i][j]]=1;
			}
		}
	}
	int ans=0;
	for(i=1 ; i<=n; i++)
	{
		if(flag[i]==0)
			ans++;
	}
	cout<<ans<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in","r",stdin);
#endif
    int i,j,k,l;
	while(scanf("%d%d", &n,&m),n||m)
	{
		init();
		memset(g,0,sizeof(g));
		int a,b;
		for(i=1; i<=m; i++)
		{
			scanf("%d%d", &a,&b);
			 g[a][b]=1;
			 g[b][a]=1;
			 
		}
	 
		for(i=1; i<=n; i++)
		{
			
			 for(j=i+1; j<=n; j++)
			 {
			 	if(!g[i][j])
			 	{
			 		insert(i,j);
			 		insert(j,i);
			  	}
			 }
		}
		getblock();
		
		solve();
	}
}

